// 移位加三法二进制转BCD码模块
module bin2bcd #(
    parameter N = 8  // 可变位宽参数，默认8位
)(
    input clk,
    input rst_n,
    input [N-1:0] binary_in,       // 输入二进制数
    output reg [19:0] bcd_out,     // 输出BCD码（最多5位十进制数）
    output reg done                // 转换完成信号
);

    // 状态机状态定义
    localparam INIT = 2'b00;
    localparam ADD3 = 2'b01;
    localparam SHIFT = 2'b10;
    localparam DONE = 2'b11;

    reg [1:0] state, next_state;
    reg [4:0] shift_cnt;           // 移位计数器
    reg [N+19:0] shift_reg;        // 移位寄存器：高20位存BCD，低N位存二进制
    reg [N-1:0] binary_reg;        // 存储输入的二进制数
    reg input_changed;             // 输入变化标志
    
    // 检测输入变化
    always @(posedge clk or negedge rst_n) 
    begin
        if (!rst_n) 
        begin
            binary_reg <= 0;
            input_changed <= 1;
        end 
        else 
        begin
            binary_reg <= binary_in;
            if (binary_reg != binary_in)
                input_changed <= 1;
            else if (state == INIT)
                input_changed <= 0;
        end
    end

    // 状态机时序逻辑
    always @(posedge clk or negedge rst_n) 
    begin
        if (!rst_n) 
        begin
            state <= INIT;
            shift_cnt <= 0;
            shift_reg <= 0;
            bcd_out <= 0;
            done <= 0;
        end 
        else 
        begin
            state <= next_state;
            
            case (state)
                INIT: 
                begin
                    shift_reg <= {{20{1'b0}}, binary_in};
                    shift_cnt <= 0;
                    done <= 0;
                end
                
                ADD3: 
                begin
                    // 对每个BCD位检查是否>=5，如果是则加3
                    // 个位 [3:0]
                    if (shift_reg[N+3:N] >= 4'd5)
                        shift_reg[N+3:N] <= shift_reg[N+3:N] + 4'd3;
                    // 十位 [7:4]
                    if (shift_reg[N+7:N+4] >= 4'd5)
                        shift_reg[N+7:N+4] <= shift_reg[N+7:N+4] + 4'd3;
                    // 百位 [11:8]
                    if (shift_reg[N+11:N+8] >= 4'd5)
                        shift_reg[N+11:N+8] <= shift_reg[N+11:N+8] + 4'd3;
                    // 千位 [15:12]
                    if (shift_reg[N+15:N+12] >= 4'd5)
                        shift_reg[N+15:N+12] <= shift_reg[N+15:N+12] + 4'd3;
                    // 万位 [19:16]
                    if (shift_reg[N+19:N+16] >= 4'd5)
                        shift_reg[N+19:N+16] <= shift_reg[N+19:N+16] + 4'd3;
                end
                
                SHIFT: 
                begin
                    shift_reg <= shift_reg << 1;
                    shift_cnt <= shift_cnt + 1;
                end
                
                DONE: 
                begin
                    bcd_out <= shift_reg[N+19:N];
                    done <= 1;
                end
            endcase
        end
    end

    // 状态机组合逻辑
    always @(*) 
    begin
        case (state)
            INIT: 
            begin
                next_state = ADD3;
            end
            
            ADD3: 
            begin
                next_state = SHIFT;
            end
            
            SHIFT: 
            begin
                if (shift_cnt == N-1)
                    next_state = DONE;
                else
                    next_state = ADD3;
            end
            
            DONE: 
            begin
                if (input_changed)
                    next_state = INIT;
                else
                    next_state = DONE;
            end
            
            default: next_state = INIT;
        endcase
    end

endmodule